#!/usr/bin/perl 
my ($myedata,$myend,$initmips,$mystart,$tgt_putchar);
open(F,qq(mips-elf-objdump -x $ARGV[0]|));
while(<F>)
{
chomp;
if(/f{8}(\w+).+_edata/){
   $myedata=qq(0x$1);
 }

if(/f{8}(\w+).+_end$/){
   $myend=qq(0x$1);
 }
if(/f{8}(\w+).+initmips$/){
   $myinitmips=qq(0x$1);
 }
if(/f{8}(\w+).+\s_start$/){
   $mystart=qq(0x$1);
 }
if(/f{8}(\w+).+\stgt_putchar$/){
   $tgt_putchar=qq(0x$1);
 }
}
printf(<< "END"
typedef	long long  off_t;	
struct callvectors {
	int     (*open) (char *, int, int);
	int     (*close) (int);
	int     (*read) (int, void *, int);
	int     (*write) (int, void *, int);
	off_t   (*lseek) (int, off_t, int);
	int     (*printf) (const char *, ...);
	void    (*cacheflush) (void);
	char    *(*gets) (char *);
};
struct callvectors *cvs;
void realinitmips(unsigned int msize);
void initmips(unsigned int msize,struct callvectors *cv)
{
    long *edata=(void *)$myedata;
    long *end=(void *)$myend;
    long *p;
	cvs=cv;
    stringserial("Uncompressing Bios");
    run_unzip(biosdata,$mystart);
    stringserial("OK,Booting Bios\\r\\n");
    for(p=edata;p<=end;p++)
    {
        *p=0;
    }
	memset($mystart-0x1000,0,0x1000);//$mystart-0x1000 for frame(registers),memset for pretty
	cv->cacheflush();
    realinitmips(msize);
}

void realinitmips(unsigned int msize)
{
	     asm ("li  \$29,$mystart-0x4000;
		       li \$2,$myinitmips;
			   move \$4,\%0;
			   jalr \$2;
			   nop;
			  1: b 1b;nop;"
          :
          : "r" (msize)
          : "\$29", "\$2","\$4");
}

static void (*rom_putchar)(char c)=(${tgt_putchar}-${mystart}+0xbfc00000);
void tgt_putchar(char c)
{
cvs->printf("%%c",c);
}
void stringserial(char *str)
{
cvs->printf("%%s",str);
}
END
);
